package com.keson.door2.util;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.hardware.Camera;
import android.media.MediaRecorder;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.alibaba.fastjson.JSONObject;
import com.arcsoft.face.ErrorInfo;
import com.arcsoft.face.FaceEngine;
import com.arcsoft.face.FaceFeature;
import com.arcsoft.face.FaceInfo;
import com.arcsoft.face.FaceSimilar;
import com.arcsoft.face.LivenessInfo;
import com.arcsoft.face.util.ImageUtils;
import com.example.yfaceapi.GPIOManager;
import com.keson.door2.MainActivity;
import com.keson.door2.bean.Face;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static android.content.ContentValues.TAG;

/**
 * Created by guoxw on 2017/10/31.
 * <!- 实现拍照,录像:  并保存图片，视频到本地></!->
 */

public class CameraUtil {

    private static MediaRecorder mediaRecorder;
    private static Camera camera;
    private static Camera.PreviewCallback previewCallback;
    /*** 标识当前是前摄像头还是后摄像头  back:0  front:1*/
    private int backOrFtont = 0;
    private static SurfaceHolder.Callback callback;
    private static Context context;
    private static SurfaceView surfaceView;
    /***录制视频的videoSize*/
    private int height, width;
    /***photo的height ,width*/
    private int heightPhoto, widthPhoto;
    //人脸检测相似度阈值
    private static float similar = 0.7f;
    private static GPIOManager gpioManager;

    private static SurfaceView surfaceViewRect;
    private static FaceEngine faceEngine;
    private static boolean isChecking = false;
    public static void create(){
        if (CameraUtil.context!=null&&CameraUtil.surfaceView!=null&&CameraUtil.surfaceViewRect!=null&&CameraUtil.faceEngine!=null){
            CameraUtil.create(CameraUtil.surfaceView, CameraUtil.surfaceViewRect, CameraUtil.context, CameraUtil.faceEngine);
        }
    }

    public static void create(final SurfaceView surfaceView, final SurfaceView surfaceViewRect, Context context, final FaceEngine faceEngine) {
        gpioManager = GPIOManager.getInstance(context);
        gpioManager.pullDownRelay();
        CameraUtil.context = context;
        CameraUtil.surfaceView = surfaceView;
        CameraUtil.surfaceViewRect = surfaceViewRect;
        CameraUtil.faceEngine = faceEngine;
        surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceView.setKeepScreenOn(true);

        final Paint paint = new Paint();
        paint.setColor(Color.RED);
        // 设置样式-空心矩形
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(10f);

        previewCallback = new Camera.PreviewCallback() {
            private Canvas canvas;

            @Override
            public void onPreviewFrame(byte[] data, Camera camera) {
                //视频数据
                List<FaceInfo> faceInfoList = new ArrayList<>();
                List<LivenessInfo> livenessInfoList = new ArrayList<>();
                int code = faceEngine.detectFaces(data, 640, 480, FaceEngine.CP_PAF_NV21, faceInfoList);
//                        计算屏幕与摄像头宽高比例
                int w = surfaceViewRect.getWidth() / 640;
                int h = surfaceViewRect.getHeight() / 480;
                if (code == ErrorInfo.MOK) {
                    if (!faceInfoList.isEmpty()) {
                        canvas = surfaceViewRect.getHolder().lockCanvas();
                        if (canvas != null) {
                            // 绘制一个矩形
                            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                            canvas.drawRect((720 - faceInfoList.get(0).getRect().right) * w, (faceInfoList.get(0).getRect().top) * h - 50, (720 - faceInfoList.get(0).getRect().left) * w, (faceInfoList.get(0).getRect().bottom) * h - 50, paint);
                            surfaceViewRect.getHolder().unlockCanvasAndPost(canvas);
                        }
                        faceEngine.process(data, 640, 480, FaceEngine.CP_PAF_NV21, faceInfoList, FaceEngine.ASF_LIVENESS);
                        faceEngine.getLiveness(livenessInfoList);
                        if (!livenessInfoList.isEmpty()) {
                            if (livenessInfoList.get(0).getLiveness() == LivenessInfo.ALIVE) {
                                FaceFeature faceFeature = new FaceFeature();
                                code = faceEngine.extractFaceFeature(data, 640, 480, FaceEngine.CP_PAF_NV21, faceInfoList.get(0), faceFeature);
                                if (code == ErrorInfo.MOK) {
                                    if (!Cache.hasIdCard&&!isChecking) {
                                        isChecking = true;
                                        for (final Face face : Cache.faceFeatureList) {
                                            FaceSimilar faceSimilar = new FaceSimilar();
                                            code = faceEngine.compareFaceFeature(faceFeature, face.getFaceFeature(), faceSimilar);
                                            if (code == ErrorInfo.MOK) {
                                                if (faceSimilar.getScore() >= similar) {
                                                    Log.i("检测到库内人员", "开闸");
//                                                            发送考勤人员ID到服务器
//                                                            face.getId()
                                                    new Thread(new Runnable() {
                                                        @Override
                                                        public void run() {
                                                            sendVistor(face.getId(),0,"",Constant.enter);
//                                                            考勤成功

                                                        }
                                                    }).start();

                                                    new Thread(new Runnable() {
                                                        @Override
                                                        public void run() {
                                                            TTSUtil.speek("认证通过");
                                                            gpioManager.pullUpGreenLight();
                                                            Cache.IDCardInfo.put("name",face.getName());
                                                            MainActivity.handler.sendMessage(MainActivity.handler.obtainMessage(100));
                                                            if (gpioManager.getRelayStatus().split("\n")[0].equals("0")) {
                                                                gpioManager.pullUpRelay();
                                                            }
                                                            try {
                                                                Thread.sleep(3000);
                                                            } catch (InterruptedException e) {
                                                                e.printStackTrace();
                                                            }
                                                            if (gpioManager.getRelayStatus().split("\n")[0].equals("1")) {
                                                                gpioManager.pullDownRelay();
                                                            }
                                                            gpioManager.pullDownGreenLight();
                                                            MainActivity.handler.sendMessage(MainActivity.handler.obtainMessage(90));
                                                        }
                                                    }).start();
                                                    isChecking = false;
                                                    return;
                                                }
                                            }
                                        }
                                        new Thread(new Runnable() {
                                            @Override
                                            public void run() {
                                                if(Cache.canMoveCard) {
                                                    TTSUtil.speek("请放置身份证");
                                                    try {
                                                        Thread.sleep(3000);
                                                    } catch (InterruptedException e) {
                                                        e.printStackTrace();
                                                    }
                                                }
                                                isChecking = false;
                                            }
                                        }).start();

                                    } else if(Cache.hasIdCard&&!isChecking){
                                        isChecking = true;
                                        Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/wltlib/zp.bmp");
                                        bitmap = ImageUtils.alignBitmapForBgr24(bitmap);
                                        byte[] bgr24 = ImageUtils.bitmapToBgr24(bitmap);
//                                        List<FaceInfo> faceInfoList = new ArrayList<>();
                                        if (bitmap == null) {
                                            Log.i("照片识别", "没有发现照片");
                                            Cache.IDCardInfo.clear();
                                            Cache.hasIdCard = false;
                                            isChecking = false;
                                            return;
                                        }
                                        int detectCode = faceEngine.detectFaces(bgr24, bitmap.getWidth(), bitmap.getHeight(), FaceEngine.CP_PAF_BGR24, faceInfoList);
                                        if (detectCode == ErrorInfo.MOK && !faceInfoList.isEmpty()) {
                                            FaceFeature faceFeature2 = new FaceFeature();
                                            detectCode = faceEngine.extractFaceFeature(bgr24, bitmap.getWidth(), bitmap.getHeight(), FaceEngine.CP_PAF_BGR24, faceInfoList.get(0), faceFeature2);
                                            if (detectCode == ErrorInfo.MOK) {
                                                FaceSimilar faceSimilar = new FaceSimilar();
                                                code = faceEngine.compareFaceFeature(faceFeature, faceFeature2, faceSimilar);
                                                if (code == ErrorInfo.MOK) {
                                                    if (faceSimilar.getScore() >= similar) {
                                                        Log.i("认证合一", "向服务请求");
                                                        new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/wltlib/zp.bmp").delete();
//                                                            发送访客人员身份证到服务器
//                                                                Cache.IDCardInfo.get("idNo");
                                                        new Thread(new Runnable() {
                                                            @Override
                                                            public void run() {
                                                                System.out.println("----------------------------"+Cache.IDCardInfo.toString());
                                                                JSONObject obj = sendVistor("0", 1, Cache.IDCardInfo.get("idNo"), Constant.enter);
                                                                if(obj.getString("msg").equals("ok")){
                                                                    Cache.IDCardInfo.put("people",obj.getString("people"));
                                                                    Cache.IDCardInfo.put("todo",obj.getString("todo"));
                                                                    MainActivity.handler.sendMessage(MainActivity.handler.obtainMessage(99));
                                                                    TTSUtil.speek("认证通过");
                                                                    gpioManager.pullUpGreenLight();
//                                                                  开闸
                                                                    if(gpioManager.getRelayStatus().split("\n")[0].equals("0")){
                                                                        gpioManager.pullUpRelay();
                                                                    }
                                                                    try {
                                                                        Thread.sleep(3000);
                                                                    } catch (InterruptedException e) {
                                                                        e.printStackTrace();
                                                                    }
                                                                    if (gpioManager.getRelayStatus().split("\n")[0].equals("1")) {
                                                                        gpioManager.pullDownRelay();
                                                                    }
                                                                    gpioManager.pullDownGreenLight();
                                                                    MainActivity.handler.sendMessage(MainActivity.handler.obtainMessage(90));
                                                                }else{
                                                                    System.out.println("不开门");
                                                                    TTSUtil.speek("请先预约");
                                                                    try {
                                                                        Thread.sleep(2000);
                                                                    } catch (InterruptedException e) {
                                                                        e.printStackTrace();
                                                                    }
                                                                }
                                                                isChecking = false;
                                                                Cache.IDCardInfo.clear();
                                                            }
                                                        }).start();
                                                    }else {
                                                        Log.i("人脸识别", "非本人,"+faceSimilar.getScore());
                                                        TTSUtil.speek("非持证人");
                                                        try {
                                                            Thread.sleep(1000);
                                                        } catch (InterruptedException e) {
                                                            e.printStackTrace();
                                                        }
                                                        isChecking = false;
                                                        Cache.IDCardInfo.clear();
                                                    }
                                                }else {
                                                    Log.i("人脸识别", "人脸对比失败,"+code);
                                                    TTSUtil.speek("人脸对比失败");
                                                    isChecking = false;
                                                    Cache.IDCardInfo.clear();
                                                }
                                            }else {
                                                Log.i("人脸识别", "查找脸部特征失败,"+detectCode);
                                                TTSUtil.speek("查找脸部特征失败");
                                                isChecking = false;
                                                Cache.IDCardInfo.clear();
                                            }
                                        }else{
                                            Log.i("人脸识别", "查找脸部失败,"+detectCode);
                                            TTSUtil.speek("查找脸部失败");
                                            isChecking = false;
                                            Cache.IDCardInfo.clear();
                                        }
//                                        Cache.IDCardInfo.clear();
                                        Cache.hasIdCard = false;
                                    }
                                }
                            }
                        }
                    } else {
                        canvas = surfaceViewRect.getHolder().lockCanvas();
                        if (canvas != null) {
                            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                            surfaceViewRect.getHolder().unlockCanvasAndPost(canvas);
                        }
                    }
                } else {
                    Log.d("人脸识别错误", "代码：" + code);
                }
            }
        };


        callback = new SurfaceHolder.Callback() {
            public void surfaceCreated(SurfaceHolder holder) {
                camera = Camera.open(0);
//                getVideoSize();
                mediaRecorder = new MediaRecorder();
                surfaceViewRect.setZOrderOnTop(true);
                surfaceViewRect.getHolder().setFormat(PixelFormat.TRANSLUCENT);

                camera.setPreviewCallback(previewCallback);
            }

            public void surfaceChanged(SurfaceHolder holder, int format,
                                       int width, int height) {
                doChange(holder);
//                focus();
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                if (camera != null) {
                    camera.release();
                    camera = null;
                }
            }
        };
        surfaceView.getHolder().addCallback(callback);
    }

    public static JSONObject sendVistor(String id, int type, String idNo, boolean enter){
        try {
            HashMap<String, String> header = new HashMap<>();
            header.put("Content-Type", "application/json;charset=UTF-8");

            JSONObject param = new JSONObject();
            param.put("id", id);
            param.put("type", type);
            param.put("idNo", idNo);
            param.put("enter", enter);
            JSONObject up = JSONObject.parseObject(HttpUtil.post(Constant.url, param.toJSONString(),header));

            System.out.println("请求参数："+param.toJSONString());
            System.out.println("返回代码："+up.toJSONString());
            System.out.println();
            if(up.getString("msg").equals("ok")) {
                Log.i("信息上传","成功");
            }
            return up;
        }catch (Exception e) {
            System.out.println("请求门禁服务失败，再次请求");
            try{
                sendVistor(id, type, idNo, enter);
            }catch (Exception e1){

            }
        }
        return null;
    }

    /**
     * Bitmap 转化为 ARGB 数据，再转化为 NV21 数据
     *
     * @param src 传入的 Bitmap，格式为 Bitmap.Config.ARGB_8888
     * @param width NV21 图像的宽度
     * @param height NV21 图像的高度
     * @return nv21 数据
     */
    public static byte[] bitmapToNv21(Bitmap src, int width, int height) {
        if (src != null && src.getWidth() >= width && src.getHeight() >=
                height) {
            int[] argb = new int[width * height];
            src.getPixels(argb, 0, width, 0, 0, width, height);
            return argbToNv21 (argb, width, height);
        } else {
            return null;
        }
    }

    /**
     * ARGB 数据转化为 NV21 数据
     *
     * @param argb argb 数据
     * @param width 宽度
     * @param height 高度
     * @return nv21 数据
     */
    private static byte[] argbToNv21(int[] argb, int width, int height) {
        int frameSize = width * height;
        int yIndex = 0;
        int uvIndex = frameSize;
        int index = 0;
        byte[] nv21 = new byte[width * height * 3 / 2];
        for (int j = 0; j < height; ++j) {
            for (int i = 0; i < width; ++i) {
                int R = (argb[index] & 0xFF0000) >> 16;
                int G = (argb[index] & 0x00FF00) >> 8;
                int B = argb[index] & 0x0000FF;
                int Y = (66 * R + 129 * G + 25 * B + 128 >> 8) + 16;
                int U = (-38 * R - 74 * G + 112 * B + 128 >> 8) + 128;
                int V = (112 * R - 94 * G - 18 * B + 128 >> 8) + 128;
                nv21[yIndex++] = (byte) (Y < 0 ? 0 : (Y > 255 ? 255 : Y));
                if (j % 2 == 0 && index % 2 == 0 && uvIndex < nv21.length -
                        2) {
                    nv21[uvIndex++] = (byte) (V < 0 ? 0 : (V > 255 ? 255 :
                            V));
                    nv21[uvIndex++] = (byte) (U < 0 ? 0 : (U > 255 ? 255 :
                            U));
                }
                ++index;
            }
        }
        return nv21;
    }

    /***
     * 等比例压缩图片
     *
     * @param bitmap
     * @param screenWidth
     * @param screenHight
     * @return
     */
    private static Bitmap getBitmap(Bitmap bitmap, int screenWidth,
                                   int screenHight) {
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        Log.e("jj", "图片宽度" + w + ",screenWidth=" + screenWidth);
        Matrix matrix = new Matrix();
        float scale = (float) screenWidth / w;
        float scale2 = (float) screenHight / h;

        scale = scale < scale2 ? scale : scale2;

        // 保证图片不变形.
        matrix.postScale(scale, scale);
        // w,h是原图的属性.
        return Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
    }

    private static void doChange(SurfaceHolder holder) {
        try {
            camera.setPreviewDisplay(holder);
            camera.setDisplayOrientation(0);
            camera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 切换摄像头
     */
    public void changeCamera() {
        int cameraCount = 0;
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        cameraCount = Camera.getNumberOfCameras();
        for (int i = 0; i < cameraCount; i++) {
            Camera.getCameraInfo(i, cameraInfo);
            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT && backOrFtont == 0) {
                camera.stopPreview();
                camera.release();
                camera = null;
                camera = Camera.open(i);
                try {
                    camera.setPreviewDisplay(surfaceView.getHolder());
                    camera.setDisplayOrientation(90);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                backOrFtont = 1;
                camera.startPreview();
                break;
            } else if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK && backOrFtont == 1) {
                camera.stopPreview();
                camera.release();
                camera = null;
                camera = Camera.open(i);
                try {
                    camera.setPreviewDisplay(surfaceView.getHolder());
                    camera.setDisplayOrientation(90);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                camera.startPreview();
                backOrFtont = 0;
                break;
            }
        }

    }

    public void stopRecord() {
        mediaRecorder.release();
        camera.release();
        mediaRecorder = null;
        camera = Camera.open();
        mediaRecorder = new MediaRecorder();
        doChange(surfaceView.getHolder());
    }


    public static void stop() {
        if (mediaRecorder != null && camera != null) {
            mediaRecorder.release();
            camera.release();
        }
    }

    public static void destroy() {
        if (mediaRecorder != null && camera != null) {
            mediaRecorder.release();
            camera.stopPreview();
            camera.setPreviewCallback(null);
            camera.release();
            mediaRecorder = null;
            camera = null;
        }
    }

    public static void stopPreview() {
        if (mediaRecorder != null && camera != null) {
            camera.stopPreview();
            camera.setPreviewCallback(null);
        }
    }

    public static void startPreview() {
        if (mediaRecorder != null && camera != null) {
            camera.setPreviewCallback(previewCallback);
            camera.startPreview();
        }
    }

    /**
     * @param path 保存的路径
     * @param name 录像视频名称(不包含后缀)
     */
    public void startRecord(String path, String name) {
        camera.unlock();
        mediaRecorder.setCamera(camera);
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        //mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW));
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mediaRecorder.setVideoEncodingBitRate(700 * 1024);
        mediaRecorder.setVideoSize(width, height);
        mediaRecorder.setVideoFrameRate(24);
        //getVideoSize();
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        mediaRecorder.setOutputFile(path + File.separator + name + ".mp4");
        File file1 = new File(path + File.separator + name + ".mp4");
        if (file1.exists()) {
            file1.delete();
        }
        mediaRecorder.setPreviewDisplay(surfaceView.getHolder().getSurface());
        /***不设置时，录制的视频总是倒着，翻屏导致视频上下翻滚*/
        mediaRecorder.setOrientationHint(0);
        try {
            mediaRecorder.prepare();
            mediaRecorder.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /***
     * 获取SupportedVideoSizes 控制输出视频width在300到600之间(尽可能小)
     * 获取PictureSize的大小(控制在w：1000-2000之间)
     */
    public void getVideoSize() {
        Camera.Parameters parameters = camera.getParameters();
        List<Camera.Size> videoSize = parameters.getSupportedVideoSizes();
        for (int i = 0; i < videoSize.size(); i++) {
            int width1 = videoSize.get(i).width;
            int height1 = videoSize.get(i).height;
            if (width1 >= 300 && width1 <= 600) {
                if (height1 >= 200 && height1 <= 600) {
                    width = width1;
                    height = height1;
                }

            }
            Log.d(TAG, "getVideoSize:----w:-- " + videoSize.get(i).width + "---h:--" + videoSize.get(i).height);
        }
        List<Camera.Size> photoSize = parameters.getSupportedPictureSizes();
        for (int i = 0; i < photoSize.size(); i++) {
            int width1 = photoSize.get(i).width;
            int height1 = photoSize.get(i).height;
            if (width1 >= 1000 && width1 <= 2000) {
                if (height1 >= 600 && height1 <=2000) {
                    widthPhoto = width1;
                    heightPhoto = height1;
                }

            }
        }

    }


    public void takePicture(String photoPath, String photoName) {

        camera.takePicture(null, null, new PictureCallBack(photoPath, photoName));
    }

    /**
     * 聚焦
     */
    public void focus(){
        Camera.Parameters parameters=camera.getParameters();
        parameters.setPictureSize(widthPhoto,heightPhoto);
        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
        camera.setParameters(parameters);
        camera.cancelAutoFocus();
    }

    /*** 拍照功能*/
    private class PictureCallBack implements Camera.PictureCallback {
        /*** 照片保存的路径和名称*/
        private String path;
        private String name;

        public PictureCallBack(String path, String name) {
            this.path = path;
            this.name = name;
        }

        @Override
        public void onPictureTaken(byte[] bytes, Camera camera) {
            File file1 = new File(path);
            if (!file1.exists()) {
                file1.mkdirs();
            }
            File file = new File(path, name);
            if (file.exists()) {
                file.delete();
            }
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(file);
                try {
                    fos.write(bytes);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            camera.startPreview();
        }
    }
}